package com.ruoyi.assets.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.assets.domain.StateVisit;
import com.ruoyi.assets.dto.StateVisitDTO;
import com.ruoyi.assets.mapper.StateVisitMapper;
import com.ruoyi.assets.service.IStateVisitService;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 访问记录Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class StateVisitServiceImpl extends ServiceImpl<StateVisitMapper, StateVisit> implements IStateVisitService {


    @Resource
    private RedisCache redisCache;

    private static final String VISIT_COUNT_KEY_PREFIX = "state_visit:count:";
    private static final String VISIT_LAST_UPDATE_KEY_PREFIX = "state_visit:last_update:";

    /**
     * 查询今日访问记录
     * 
     * @return 今日访问记录列表
     */
    @Override
    public List<StateVisit> selectTodayVisits() {
        Date today = DateUtils.getNowDate();
        return baseMapper.selectTodayVisits(today);
    }
    
    /**
     * 获取今日总访问量
     * 
     * @return 今日总访问量
     */
    @Override
    public Integer selectTodayTotalVisits() {
        Date today = DateUtils.getNowDate();
        return baseMapper.selectTodayTotalVisits(today);
    }
    
    /**
     * 记录资产访问
     * 
     * @param assetId 资产ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recordVisit(Long assetId) {
        if (assetId == null) {
            return false;
        }
        
        // 查询今日是否已有该资产的访问记录
        StateVisit visit = baseMapper.selectVisitByAssetId(assetId);
        
        if (visit != null) {
            // 已有记录，更新访问量
            visit.setVisitNum(visit.getVisitNum() + 1);
            return updateById(visit);
        } else {
            // 无记录，新增
            StateVisit newVisit = new StateVisit();
            newVisit.setAssetId(assetId);
            newVisit.setVisitNum(1);
            return save(newVisit);
        }
    }
    
    /**
     * 获取按月访问量统计
     * 
     * @param months 过去几个月
     * @return 月度访问统计
     */
    @Override
    public List<Map<String, Object>> getMonthlyVisitTrends(int months) {
        // 获取当前日期
        Date endDate = DateUtils.getNowDate();
        
        // 计算开始日期（过去n个月）
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        calendar.add(Calendar.MONTH, -months);
        Date startDate = calendar.getTime();
        
        // 查询月度访问统计
        return baseMapper.countMonthlyVisits(startDate, endDate);
    }

    @Override
    public void handleFromConsumeMessage(StateVisitDTO dto) {
        String key = dto.getCode() + dto.getType() + dto.getId();
        if (redisCache.hasKey(key)) {
            return;
        }

        // 访问计数缓存key
        String countKey = VISIT_COUNT_KEY_PREFIX + dto.getType();
        // 最后更新时间缓存key
        String lastUpdateKey = VISIT_LAST_UPDATE_KEY_PREFIX + dto.getType();
        
        // 增加缓存中的计数
        Integer count = redisCache.getCacheObject(countKey);
        if (count == null) {
            count = 1;
        } else {
            count += 1;
        }
        redisCache.setCacheObject(countKey, count);

        // 获取最后更新时间
        Long lastUpdate = redisCache.getCacheObject(lastUpdateKey);
        long currentTime = System.currentTimeMillis();
        
        // 如果是第一次访问或者距离上次更新超过1分钟，则更新数据库
        if (lastUpdate == null || (currentTime - lastUpdate) >= 60000) {
            synchronized (this) {
                // 双重检查，确保在并发情况下只有一个线程执行更新
                lastUpdate = redisCache.getCacheObject(lastUpdateKey);
                if (lastUpdate == null || (currentTime - lastUpdate) >= 60000) {
                    // 查询今天的访问记录
                    StateVisit articleVisit = lambdaQuery()
                            .eq(StateVisit::getType, dto.getType())
                            .apply("DATE(create_time) = CURRENT_DATE")
                            .last("limit 1")
                            .one();
                    
                    // 获取当前缓存中的计数并重置
                    count = redisCache.getCacheObject(countKey);
                    if (count == null) {
                        count = 1;
                    }
                    redisCache.deleteObject(countKey);

                    if (articleVisit == null) {
                        articleVisit = new StateVisit();
                        articleVisit.setVisitNum(count);
                        articleVisit.setType(dto.getType());
                    } else {
                        articleVisit.setVisitNum(articleVisit.getVisitNum() + count);
                    }
                    
                    saveOrUpdate(articleVisit);
                    
                    // 更新最后更新时间
                    redisCache.setCacheObject(lastUpdateKey, currentTime);
                }
            }
        }

        // 设置访问标记，防止重复访问
        redisCache.setCacheObject(key, 1, 1, TimeUnit.DAYS);
    }
}